package log

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"time"

	"github.com/gin-gonic/gin"
)

var (
	infoLogger    *log.Logger
	errorLogger   *log.Logger
	warningLogger *log.Logger
	debugLogger   *log.Logger
)

func init() {
	flags := log.Ldate | log.Ltime | log.Lmicroseconds
	infoLogger = log.New(os.Stdout, "INFO: ", flags)
	errorLogger = log.New(os.Stderr, "ERROR: ", flags)
	warningLogger = log.New(os.Stdout, "WARNING: ", flags)
	debugLogger = log.New(os.Stdout, "DEBUG: ", flags)
}

func getFileAndLine() string {
	_, file, line, ok := runtime.Caller(2)
	if !ok {
		file = "???"
		line = 0
	}
	return fmt.Sprintf("%s:%d", file, line)
}

func Info(format string, v ...interface{}) {
	loc := getFileAndLine()
	msg := fmt.Sprintf(format, v...)
	infoLogger.Printf("[%s] %s", loc, msg)
}

func Error(format string, v ...interface{}) {
	loc := getFileAndLine()
	msg := fmt.Sprintf(format, v...)
	errorLogger.Printf("[%s] %s", loc, msg)
}

func Warning(format string, v ...interface{}) {
	loc := getFileAndLine()
	msg := fmt.Sprintf(format, v...)
	warningLogger.Printf("[%s] %s", loc, msg)
}

func Debug(format string, v ...interface{}) {
	loc := getFileAndLine()
	msg := fmt.Sprintf(format, v...)
	debugLogger.Printf("[%s] %s", loc, msg)
}

func RequestLog(c *gin.Context, startTime time.Time, msg string) {
	endTime := time.Now()
	latency := endTime.Sub(startTime)
	clientIP := c.ClientIP()
	method := c.Request.Method
	path := c.Request.URL.Path

	Info("[Request] %s | %s %s | %s | %v | %s",
		clientIP,
		method,
		path,
		latency,
		c.Writer.Status(),
		msg,
	)
}
